package com.mico.micochange.server;

import com.alibaba.fastjson.JSONObject;
import com.mico.micochange.common.ExchangeCacheUtils;
import com.mico.micochange.common.RSAUtil;
import com.mico.xchange.binance.BinanceExchange;
import com.mico.xchange.bitstamp.BitstampExchange;
import com.mico.xchange.bittrex.BittrexExchange;
import com.mico.xchange.chaoex.ChaoexExchange;
import com.mico.xchange.chaoex.service.ChaoexHmacDigest;
import com.mico.xchange.fcoin.FCoinExchange;
import com.mico.xchange.huobi.HuobiExchange;
import com.mico.xchange.okcoin.OkCoinExchange;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by chenst on 2018/5/6.
 */
public abstract class MicoThread extends Thread{

    private static final Logger LOG = LoggerFactory.getLogger(MicoThread.class);
    //创建连接对象，作用返回处理结果
    private IoSession session;
    //输入参数
    private String message;

    public MicoThread(IoSession session,String message){
        this.session = session;
        this.message = message;
    }

    @Override
    public void run(){
        //处理输入参数
        String uuid = UUID.randomUUID().toString();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        JSONObject json = (JSONObject) JSONObject.parse(message);
        LOG.error(uuid + " input["+sdf.format(new Date())+"] @@"+message);

        if(!"mico".equals(json.getString("exchange"))){
            //对账户解密
            if (decryptAppInfo(uuid, json)) return;
        }

        Map retMap = doDeal(json);
        String retStr = JSONObject.toJSONString(retMap);
        LOG.error(uuid + " out["+sdf.format(new Date())+"] ##"+retStr);
        //返回数据
        session.write(retStr);
    }

    /**
     * 对app_key和app_secret解密
     * @param uuid
     * @param json
     * @return
     */
    private boolean decryptAppInfo(String uuid, JSONObject json) {
        String app_key = json.getString("apiKey");
        String app_secret = json.getString("secretKey");
        String loginPwd = json.getString("loginPwd");

        String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCNdvOXY4XIRZvjcanVdOAc9VVmoW_5zCOxbmfXQaiARsmRqW1KImk-KtFel4s3qIYden6J3vsS0Ko9LirWFJtvymCAojnvW5dwzgEhY6adM8EMELPfXDf8V5o0R7Y-h3utKSaVD37ZCr1uz0CI-P1jqdk3ZVMx5noGkpVTtgLgNwIDAQAB";

        //对账户信息解密
        String decAppKey = null;
        String decAppSecret = null;
        String decLoginPwd = null;
        try {
            decAppKey = RSAUtil.publicDecrypt(app_key,RSAUtil.getPublicKey(publicKey));
            decAppSecret = RSAUtil.publicDecrypt(app_secret,RSAUtil.getPublicKey(publicKey));
            if(null != loginPwd)
                decLoginPwd = RSAUtil.publicDecrypt(loginPwd,RSAUtil.getPublicKey(publicKey));
        } catch (Exception e) {
            e.printStackTrace();
            Map retMap = new HashMap();
            retMap.put("err","账户信息解密失败，请确认！");

           /* BigDecimal bigDecimal = new BigDecimal(0E-8777);
            if(bigDecimal.toString().indexOf("E")>-1){
                Double var = Double.parseDouble(bigDecimal.toString());
                bigDecimal = new BigDecimal(var.toString());
            }
            retMap.put("test",bigDecimal);*/
            String retStr = JSONObject.toJSONString(retMap);
            LOG.error(uuid + " out ##"+retStr);
            //返回数据
            session.write(retStr);
            return true;
        }

        json.put("apiKey",decAppKey);
        json.put("secretKey",decAppSecret);
        if(null != loginPwd)
            json.put("loginPwd",decLoginPwd);
        return false;
    }

    /**
     * @param json
     * @return
     */
    public Map doDeal(JSONObject json){
        String source = (String)json.get("exchange");
        Map retMap = new HashMap();
        String exchange = "";
        try {
            if ("hb".equals(source)) {
                exchange = HuobiExchange.class.getName();
                retMap = doHuobiChange(json);
            } else if ("ba".equals(source)) {
                exchange = BinanceExchange.class.getName();
                retMap = doBinanceChange(json);
            }  else if ("ck".equals(source)) {
                exchange = ChaoexExchange.class.getName();
                retMap = doChaoexChange(json);
            }  else if ("bitstamp".equals(source)) {
                exchange = BitstampExchange.class.getName();
                retMap = doBitstampChange(json);
            } else if ("mico".equals(source)) {
                retMap = doMicoChange(json);
            }else if ("ok".equals(source)) {
                exchange = OkCoinExchange.class.getName();
                retMap = doOkexChange(json);
            } else if ("bittrex".equals(source)) {
                exchange = BittrexExchange.class.getName();
                retMap = doBittrexExchange(json);
            }else if ("fc".equals(source)) {
                exchange = FCoinExchange.class.getName();
                retMap = doFCoinExchange(json);
            } else {
                retMap.put("err", "暂不支持此交易所！");
            }
        }catch (Exception ex){
            ex.printStackTrace();
            String errMsg = "";
            if(ex.getMessage()==null || "".equals(ex.getMessage())){
                errMsg = "交易失败，请联系外联平台管理员！";
            }else{
                errMsg = ex.getMessage();
                try {
                    //如果交易所的通讯录缓存交易对等信息失效，重新获取交易一遍
                    if (errMsg != null && errMsg.indexOf("Huobi doesn't support the specail currency") >= 0) {
                        ExchangeCacheUtils.putNewExchange(exchange, json.get("apiKey").toString(), json.get("secretKey").toString());
                        retMap = doDealFinal(json);
                        return retMap;
                    }
                }catch (Exception finalEx){
                    finalEx.printStackTrace();
                    errMsg = finalEx.getMessage();
                }
            }
            retMap.put("err",errMsg);
        }

        return retMap;
    }



    /**
     * @param json
     * @return
     */
    public Map doDealFinal(JSONObject json){
        String source = (String)json.get("exchange");
        Map retMap = new HashMap();
        try {
            if ("huobi".equals(source)) {
                retMap = doHuobiChange(json);
            } else if ("binance".equals(source)) {
                retMap = doBinanceChange(json);
            }  else if ("chaoke".equals(source)) {
                retMap = doChaoexChange(json);
            }  else if ("bitstamp".equals(source)) {
                retMap = doBitstampChange(json);
            } else if ("ok".equals(source)) {
                retMap = doOkexChange(json);
            } else if ("mico".equals(source)) {
                retMap = doMicoChange(json);
            } else if ("bittrex".equals(source)) {
                retMap = doBittrexExchange(json);
            }else if ("fc".equals(source)) {
                retMap = doFCoinExchange(json);
            }else {
                retMap.put("err", "暂不支持此交易所！");
            }
        }catch (Exception ex){
            ex.printStackTrace();
            String errMsg = "";
            if(ex.getMessage()==null || "".equals(ex.getMessage())){
                errMsg = "交易失败，请联系外联平台管理员！";
            }else{
                errMsg = ex.getMessage();
            }
            retMap.put("err",errMsg);
        }
        return retMap;
    }

    /**
     * @param json 输入参数
     * @return 返回处理结果
     */
    public abstract Map doHuobiChange(JSONObject json) throws Exception;

    /**
     * @param json 输入参数
     * @return 返回处理结果
     */
    public abstract Map doBinanceChange(JSONObject json) throws Exception;


    /**
     * @param json 输入参数
     * @return 返回处理结果
     */
    public Map doBitZChange(JSONObject json) throws Exception{
        throw new Exception("not imp");
    };

    /**
     * @param json 输入参数
     * @return 返回处理结果
     */
    public abstract Map doChaoexChange(JSONObject json) throws Exception;

    /**
     * @param json 输入参数
     * @return 返回处理结果
     */
    public abstract Map doBitstampChange(JSONObject json) throws Exception;

    /**
     * @param json 输入参数
     * @return 返回处理结果
     */
    public abstract Map doOkexChange(JSONObject json) throws Exception;

    /**
     * @param json 输入参数
     * @return 返回处理结果
     */
    public Map doMicoChange(JSONObject json) throws Exception{
        return null;
    }

    /**
     * @param json 输入参数
     * @return 返回处理结果
     */
    public Map doBittrexExchange(JSONObject json) throws Exception{
        throw new Exception("not imp");
    };



    /**
     * @param json 输入参数
     * @return 返回处理结果
     */
    public abstract Map doFCoinExchange(JSONObject json) throws Exception;

}
